/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
import assert from 'assert';
import { EditCodeIntent } from '../../src/extension/intents/node/editCodeIntent';
import { ConfigKey } from '../../src/platform/configuration/common/configurationService';
import { ssuite, stest } from '../base/stest';
import { simulateInlineChat } from '../simulation/inlineChatSimulator';
import { toFile } from '../simulation/stestUtil';

ssuite({ title: 'custom instructions', location: 'inline' }, () => {
	let configurations = [
		{
			key: ConfigKey.CodeGenerationInstructions,
			value: [
				{ "text": "Field names should start with the prefix 'f'", "language": "typescript" },
				{ "text": "Add a comment: 'Generated by Copilot'" }
			]
		}
	];
	stest({ description: 'Custom instructions for language', configurations }, (testingServiceCollection) => {
		return simulateInlineChat(testingServiceCollection, {
			files: [toFile({ fileName: "hello.ts", fileContents: "\n\n" })],
			queries: [
				{
					file: 'hello.ts',
					selection: [0, 0, 0, 0],
					query: [
						`/edit add a class named 'Foo' with a field 'address' along with getters and setters`,
					].join('\n'),
					expectedIntent: EditCodeIntent.ID,
					validate: async (outcome, workspace, accessor) => {
						assert.strictEqual(outcome.type, 'inlineEdit');
						assert.ok(outcome.fileContents.includes(' fAddress'));
						assert.ok(outcome.fileContents.includes('Generated by Copilot'));
					}
				}
			]
		});
	});
	configurations = [
		{
			key: ConfigKey.CodeGenerationInstructions,
			value: [
				{ "text": "Field names should start with the prefix 'f'", "language": "javascript" },
				{ "text": "Add a comment: 'Generated by Copilot'", "language": "java" },
			]
		}
	];
	stest({ description: 'Custom instructions not applicable to language', configurations }, (testingServiceCollection) => {
		return simulateInlineChat(testingServiceCollection, {
			files: [
				toFile({ fileName: "hello.ts", fileContents: "\n\n" }),
			],
			queries: [
				{
					file: 'hello.ts',
					selection: [0, 0, 0, 0],
					query: [
						`/edit add a class named 'Foo' with a field 'address' along with getters and setters`,
					].join('\n'),
					expectedIntent: EditCodeIntent.ID,
					validate: async (outcome, workspace, accessor) => {
						assert.strictEqual(outcome.type, 'inlineEdit');
						assert.ok(!outcome.fileContents.includes(' fAddress'));
						assert.ok(!outcome.fileContents.includes('Generated by Copilot'));
					}
				}
			]
		});
	});
	const configurations2 = [
		{
			key: ConfigKey.CodeGenerationInstructions,
			value: [
				{ "file": "code-guidelines.md" }
			]
		}
	];
	stest({ description: 'Custom instructions from file', configurations: configurations2 }, (testingServiceCollection) => {
		return simulateInlineChat(testingServiceCollection, {
			files: [
				toFile({ fileName: "hello.ts", fileContents: "\n\n" }),
				toFile({ fileName: "code-guidelines.md", fileContents: "\n\nField names should start with the prefix '__'\n" })
			],
			queries: [
				{
					file: 'hello.ts',
					selection: [0, 0, 0, 0],
					query: [
						`/edit add a class named 'Foo' with a field 'address' along with getters and setters`,
					].join('\n'),
					expectedIntent: EditCodeIntent.ID,
					validate: async (outcome, workspace, accessor) => {
						assert.strictEqual(outcome.type, 'inlineEdit');
						assert.ok(outcome.fileContents.includes(' __address'));
					}
				}
			]
		});
	});
	const configurations3 = [
		{
			key: ConfigKey.CodeGenerationInstructions,
			value: [
				{ "file": "code-guidelines1.md" },
				{ "text": "Add a comment: 'Generated by Copilot'", "language": "typescript" },
			]
		}
	];
	stest({ description: 'Custom instructions with missing file', configurations: configurations3 }, (testingServiceCollection) => {
		return simulateInlineChat(testingServiceCollection, {
			files: [
				toFile({ fileName: "hello.ts", fileContents: "\n\n" }),
				toFile({ fileName: "code-guidelines.md", fileContents: "\n\nField names should start with the prefix '__'\n" })
			],
			queries: [
				{
					file: 'hello.ts',
					selection: [0, 0, 0, 0],
					query: [
						`/edit add a class named 'Foo' with a field 'address' along with getters and setters`,
					].join('\n'),
					expectedIntent: EditCodeIntent.ID,
					validate: async (outcome, workspace, accessor) => {
						assert.strictEqual(outcome.type, 'inlineEdit');
						assert.ok(!outcome.fileContents.includes(' __address'));
						assert.ok(outcome.fileContents.includes('Generated by Copilot'));
					}
				}
			]
		});
	});
});
